/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.debugger.debug; import java.util.*; import javax.swing.SwingUtilities; import sun.tools.debug.RemoteThreadGroup; import sun.tools.debug.RemoteThread; import org.openide.debugger.DebuggerException; import org.netbeans.modules.debugger.support.AbstractThreadGroup; import org.netbeans.modules.debugger.support.AbstractThread; import org.netbeans.modules.debugger.support.util.*; /** * Inner representation of one thread group. */ public class ToolsThreadGroup extends AbstractThreadGroup { // variables ................................................................. ToolsDebugger debugger; private HashMap oldContent = new HashMap (); /** Thread group which are representated by this AbstractThreadGroup instance */ private RemoteThreadGroup threadGroup; // init ............................................................................ /** * Creates empty ThreadGroup. */ ToolsThreadGroup ( ToolsDebugger debugger, ToolsThreadGroup parentThreadGroup ) { this (debugger, parentThreadGroup, null); } /** * Creates ThreadGroup for some remote thread group. * * @param threadGroup RemoteThreadGroup which must be represented by this AbstractThread * instance. Id can be <CODE>null</CODE>. */ ToolsThreadGroup ( ToolsDebugger debugger, ToolsThreadGroup parentThreadGroup, RemoteThreadGroup threadGroup ) { super (parentThreadGroup); this.threadGroup = threadGroup; this.debugger = debugger; } // implementation of AbstractThreadGroup ............................................. /** * Getter for the name of thread group property. * * @return name of thread. */ public String getName () throws DebuggerException { if (debugger.synchronizer == null) return debugger.bundle.getString ("CTL_Thread_group_root");; if (threadGroup == null) return debugger.bundle.getString ("CTL_Thread_group_root"); try { return (String) new Protector ("AbstractThreadGroup.getName") { // NOI18N public Object protect () throws Exception { return threadGroup.getName (); } }.throwAndWait (debugger.synchronizer, debugger.killer); } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; throw new DebuggerException (e); } } // helper methods ..................................................................... /** * Sets RemoteThreadGroup for this object. * * @param threadGroup RemoteThreadGroup which must be represented by this ToolsThread * instance. Id can be <CODE>null</CODE>. */ void setRemoteThreadGroup (RemoteThreadGroup threadGroup) { this.threadGroup = threadGroup; try { threadChanged (); } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; debugger.println (debugger.bundle.getString ("EXC_Debugger") + ": " + e, debugger.ERR_OUT); return; } } /** * Updates state of threads in this thread group. */ void threadChanged () { RequestSynchronizer rs = debugger.synchronizer; if (rs == null) return; // synchronized (rs) { try { Iterator g = directChildren (); HashMap newContent = new HashMap (); ToolsThreadGroup ttg; while (g.hasNext ()) { RemoteThreadGroup rtg = (RemoteThreadGroup) g.next (); if ((ttg = (ToolsThreadGroup) oldContent.get (rtg)) == null) { //new threadGroup ttg = new ToolsThreadGroup (debugger, this, rtg); try { debugger.println (debugger.bundle.getString ("CTL_New_thread_group") + ": " + ttg.getName (), debugger.ERR_OUT); // NOI18N } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; } addThreadGroup (ttg); } else { //existing threadGroup oldContent.remove (rtg); } ttg.threadChanged (); newContent.put (rtg, ttg); } //threads if (threadGroup != null) { RemoteThread[] t = listThreads (); ToolsThread tt; int i, k = t.length; for (i = 0; i < k; i++) { try { String stat = getStatus (t [i]); if ((stat != null) && stat.equals ("zombie")) { // NOI18N continue; } } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; } if ((tt = (ToolsThread) oldContent.get (t [i])) == null) { //new thread tt = new ToolsThread (debugger, this, t [i]); try { debugger.println (debugger.bundle.getString ("CTL_New_thread") + ": " + tt.getName (), debugger.ERR_OUT); // NOI18N } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; } addThread (tt); } else { //existing thread tt.threadChanged (); oldContent.remove (t [i]); } newContent.put (t [i], tt); } } //remove threads Iterator it = oldContent.values ().iterator (); while (it.hasNext ()) { Object o = it.next (); if (o instanceof ToolsThread) { ToolsThread t = (ToolsThread) o; try { debugger.println (debugger.bundle.getString ("CTL_Thread_destroyed") + ": " + t.getName (), debugger.ERR_OUT); // NOI18N } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; } removeThread (t); } else { ToolsThreadGroup gg = (ToolsThreadGroup) o; try { debugger.println (debugger.bundle.getString ("CTL_Thread_group_destroyed") + ": " + gg.getName (), debugger.ERR_OUT); // NOI18N } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; } removeThreadGroup (gg); } } oldContent = newContent; } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; } // } } /** * Finds ToolsThread for given RemoteThread recursivelly. */ ToolsThread getThread (RemoteThread rt) { AbstractThread[] tt = getThreads (); ToolsThread r; int i, k = tt.length; for (i = 0; i < k; i++) if ((r = (ToolsThread) tt [i]).getRemoteThread ().equals (rt)) return r; AbstractThreadGroup[] ttg = getThreadGroups (); k = ttg.length; for (i = 0; i < k; i++) if ((r = ((ToolsThreadGroup) ttg [i]).getThread (rt)) != null) return r; return null; } // pricvate methods .......................................................................................... /** * Returns threadgroups for this thread group. * UNSAFE METHOD !!!!!!!!!!!!!!! * @return children of the threadgroup not recursively. */ private Iterator directChildren () throws Exception { RemoteThreadGroup[] all = listThreadGroups (); HashSet ch = new HashSet (Arrays.asList (all)); int i, k = all.length; for (i = 0; i < k; i++) { RemoteThreadGroup[] subChildren = debugger.remoteDebugger.listThreadGroups ( all [i] ); int j, l = subChildren.length; for (j = 0; j < l; j++) ch.remove (subChildren [j]); } return ch.iterator (); } /** * Returns array of thread from current thread group. */ private RemoteThread[] listThreads () { if (debugger.synchronizer == null) return new RemoteThread [0]; return (RemoteThread[]) new Protector ("ToolsThreadGroup.listThreads") { // NOI18N public Object protect () throws Exception { try { return threadGroup.listThreads (false); } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; } return new RemoteThread [0]; } }.wait (debugger.synchronizer, debugger.killer); } /** * Returns array of all thread groups from current thread group. */ private RemoteThreadGroup[] listThreadGroups () { if (debugger.synchronizer == null) return new RemoteThreadGroup [0]; return (RemoteThreadGroup[]) new Protector ("ToolsThreadGroup.listThreadGroups") { // NOI18N public Object protect () throws Exception { try { return debugger.remoteDebugger.listThreadGroups (threadGroup); } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; } return new RemoteThreadGroup [0]; } }.wait (debugger.synchronizer, debugger.killer); } /** * Returns status of given thread. */ private String getStatus (final RemoteThread t) { if (debugger.synchronizer == null) return ""; // NOI18N return (String) new Protector ("ToolsThreadGroup.getStatus") { // NOI18N public Object protect () throws Exception { try { return t.getStatus (); } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; } return new RemoteThreadGroup [0]; } }.wait (debugger.synchronizer, debugger.killer); } } /* * Log * 12 Gandalf 1.11 1/13/00 Daniel Prusa NOI18N * 11 Gandalf 1.10 1/6/00 Jan Jancura Refresh of Threads & * Watches, Weakization of Nodes * 10 Gandalf 1.9 11/29/99 Jan Jancura Bug 3341 - bad \n in * output of debugger * 9 Gandalf 1.8 11/8/99 Jan Jancura Somma classes renamed * 8 Gandalf 1.7 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 7 Gandalf 1.6 8/17/99 Jan Jancura Actions for session * added & Thread group current property * 6 Gandalf 1.5 7/24/99 Jan Jancura Bug in Suspend / resume * thread in enterprise deb. * 5 Gandalf 1.4 7/13/99 Jan Jancura * 4 Gandalf 1.3 7/2/99 Jan Jancura Session debugging * support * 3 Gandalf 1.2 6/9/99 Ian Formanek ---- Package Change To * org.openide ---- * 2 Gandalf 1.1 6/4/99 Jan Jancura * 1 Gandalf 1.0 6/1/99 Jan Jancura * $ */